#include <cppunit/config/SourcePrefix.h>
#include "QueryEvaluatorTest.h"
#include "QueryPreProcessor.h"
#include <iostream>
#include <string>
#include "Parser.h"

using namespace std;

void QueryEvaluatorTest::setUp() {
}

void QueryEvaluatorTest::tearDown() {
}

CPPUNIT_TEST_SUITE_REGISTRATION(QueryEvaluatorTest);

void QueryEvaluatorTest::testEvaluateMain() {
	/**************************Initialising*****************************/
	PKB* testPKB = new PKB();
	qe = new QueryEvaluator(testPKB);
	QueryPreProcessor* qpp = new QueryPreProcessor(testPKB);
	Parser* p = new Parser(testPKB);

	string filename = "../Release/alfathiOneTidy.txt";
	vector<vector<string>> parsed;
	vector<string> final;
	string queryParent, queryParent1, queryParentPattern, queryParentPattern1, queryFollows, queryFollows1, queryFollows2;
	queryParent = "assign a; Select a such that Parent(3, a)";
	queryParent1 = "assign a1; Select a1 such that Parent(3, a1)";
	queryParentPattern = "assign a; Select a such that Parent(3, a) pattern a(_, _\"y+v\"_)";
	queryParentPattern1 = "assign a; Select a pattern a(_, _\"y+v\"_) such that Parent(3, a)" ;
	queryFollows = "stmt s1, s2; Select s1 such that Follows(s1, s2)";
	
	/****Got error when testing***/
	queryFollows1 = "stmt s1, s2; Select s1 such that Follows*(s1, s2)";
	queryFollows2 = "stmt s1, s2, s3; Select s1 such that Follows*(s1, s2) and Follows*(s2, s3)";
	
	/**************************Initialising*****************************/

	cout << "Testing: vector<string> evaluate(vector<vector<string>>)" << endl; 
	p->startParsing(filename);
	parsed = qpp->processQuery(queryParent);
	final = qe->evaluate(parsed);

	cout << "- Testing Parent in Query Evaluation process" << endl;
	CPPUNIT_ASSERT(final.at(0) == "11");
	CPPUNIT_ASSERT(final.at(1) == "4");
	CPPUNIT_ASSERT(final.at(2) == "5");
	CPPUNIT_ASSERT(final.at(3) == "6");

	parsed.empty();
	final.empty();

	parsed = qpp->processQuery(queryParent1);
	final = qe->evaluate(parsed);

	cout << "- Testing Parent in Query Evaluation process" << endl;
	CPPUNIT_ASSERT(final.at(0) == "11");
	CPPUNIT_ASSERT(final.at(1) == "4");
	CPPUNIT_ASSERT(final.at(2) == "5");
	CPPUNIT_ASSERT(final.at(3) == "6");

	parsed.empty();
	final.empty();

	cout << "- Testing Rearranged Pattern and Parent in Query Evaluation process" << endl;
	parsed = qpp->processQuery(queryParentPattern1);
	final = qe->evaluate(parsed);
	CPPUNIT_ASSERT(final.at(0) == "11");
	CPPUNIT_ASSERT(final.at(1) == "5");

	parsed.empty();
	final.empty();

	cout << "- Testing Pattern and Parent in Query Evaluation process" << endl;
	parsed = qpp->processQuery(queryParentPattern);
	final = qe->evaluate(parsed);
	CPPUNIT_ASSERT(final.at(0) == "11");
	CPPUNIT_ASSERT(final.at(1) == "5");
	
	parsed.empty();
	final.empty();

	cout << "- Testing Follows* in Query Evaluation process" << endl;
	parsed = qpp->processQuery(queryFollows);
	final = qe->evaluate(parsed);
	CPPUNIT_ASSERT(final.at(0) == "1");
	CPPUNIT_ASSERT(final.at(1) == "11");
	CPPUNIT_ASSERT(final.at(2) == "13");
	CPPUNIT_ASSERT(final.at(3) == "14");
	CPPUNIT_ASSERT(final.at(4) == "15");
	CPPUNIT_ASSERT(final.at(5) == "16");
	CPPUNIT_ASSERT(final.at(6) == "17");
	CPPUNIT_ASSERT(final.at(7) == "18");
	CPPUNIT_ASSERT(final.at(8) == "19");
	CPPUNIT_ASSERT(final.at(9) == "2");
	CPPUNIT_ASSERT(final.at(10) == "20");
	CPPUNIT_ASSERT(final.at(11) == "23");
	CPPUNIT_ASSERT(final.at(12) == "24");
	CPPUNIT_ASSERT(final.at(13) == "25");
	CPPUNIT_ASSERT(final.at(14) == "26");
	CPPUNIT_ASSERT(final.at(15) == "28");
	CPPUNIT_ASSERT(final.at(16) == "30");
	CPPUNIT_ASSERT(final.at(17) == "31");
	CPPUNIT_ASSERT(final.at(18) == "33");
	CPPUNIT_ASSERT(final.at(19) == "4");
	CPPUNIT_ASSERT(final.at(20) == "5");
	CPPUNIT_ASSERT(final.at(21) == "6");
	CPPUNIT_ASSERT(final.at(22) == "7");
	CPPUNIT_ASSERT(final.at(23) == "8");
	CPPUNIT_ASSERT(final.at(24) == "9");

	cout << "Test OK: vector<string> evaluate(vector<vector<string>>)" << endl;
};